home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / editor / chktex.lha / chktex / source / Utility.c < prev    next >
C/C++ Source or Header  |  1996-01-25  |  10KB  |  577 lines

  1. /*
  2.  *  ChkTeX v1.2, utility functions.
  3.  *  Copyright (C) 1995-96 Jens T. Berger Thielemann
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  Contact the author at:
  20.  *        Jens Berger
  21.  *        Spektrumvn. 4
  22.  *        N-0666 Oslo
  23.  *        Norway
  24.  *        E-mail: <jensthi@ifi.uio.no>
  25.  *
  26.  *
  27.  */
  28.  
  29. #include "ChkTeX.h"
  30.  
  31. /***************************** SUPPORT FUNCTIONS ************************/
  32.  
  33.  
  34. /*
  35.  * Copies a string with a maximum length of `len' starting at `pos' in
  36.  * `source' into `dest'.
  37.  * Returns -1 if the pos value is beyond the length of the source value,
  38.  * else NULL.
  39.  */
  40.  
  41.  
  42. #ifdef STRMID_NEED
  43. WORD strmid(const STRPTR source, STRPTR dest, LONG pos, LONG len)
  44. {
  45.     ULONG    slen = strlen(source);
  46.     STRPTR    Start;
  47.     WORD    Retval = -1;
  48.  
  49.     if(len)
  50.     {
  51.         if(slen > pos)
  52.         {
  53.             Start = &source[pos];
  54.  
  55.  
  56.             while((len-- > 0) && (*dest++ = *Start++))
  57.                 ;
  58.             *dest++ = 0;
  59.  
  60.             if(len == -1)
  61.                 Retval = 0;
  62.         }
  63.     }
  64.     else
  65.     {
  66.         *dest = 0;
  67.         Retval = 0L;
  68.     }
  69.  
  70.     return(Retval);
  71. }
  72. #endif
  73.                   
  74.  
  75.  
  76. /*
  77.  * Determine whether a file exists.
  78.  *
  79.  */
  80.  
  81.  
  82. BOOL fexists(STRPTR Filename)
  83. {
  84.     BOOL    Retval = FALSE;
  85.  
  86. #if defined(F_OK) && defined(R_OK)
  87.     Retval = access(Filename, F_OK|R_OK) == 0;
  88. #else
  89.     {
  90.         FILE    *fh;
  91.  
  92.         if(fh = fopen(Filename, "r"))
  93.             {
  94.             Retval = TRUE;
  95.             fclose(fh);
  96.         }
  97.     }
  98. #endif
  99.     return(Retval);
  100. }
  101.  
  102.  
  103.  
  104. /*
  105.  * 'Safe' memset() replacement.
  106.  * Just tries to check the parameters, so that the risk of killing
  107.  * innocent memory is lowered.
  108.  * Please note that the `n' parameter now is an signed longword, not
  109.  * an size_t. Won't permit that `n' exceeds BUFLEN, nor negative sizes.
  110.  * Returns `to' if some memset()'ing was done, NULL if not.
  111.  */
  112.  
  113. APTR sfmemset(APTR to, int c, LONG n)
  114. {
  115.     if(to && (n > 0))
  116.     {
  117.         n = min(n, BUFLEN);
  118.  
  119.         return(memset(to, c, (size_t) n));
  120.     }
  121.     return(NULL);
  122. }
  123.  
  124. /*
  125.  * Concatenates the `File' string to the `Dir' string, leaving the result
  126.  * in the `Dir' buffer. Takes care of inserting `directory' characters;
  127.  * if we've got the strings "/usr/foo" and "bar", we'll get
  128.  * "/usr/foo/bar".
  129.  *
  130.  * Behaviour somewhat controlled by the macros SLASH and DIRCHARS in the
  131.  * .h file.
  132.  *
  133.  */
  134.  
  135. void tackon(STRPTR Dir, const STRPTR File)
  136. {
  137.     UBYTE    EndC;
  138.     ULONG    SLen;
  139.  
  140.     if(Dir && (SLen = strlen(Dir)))
  141.     {
  142.         EndC = Dir[SLen -1];
  143.         ifn(strchr(DIRCHARS, EndC))
  144.         {
  145.             Dir[SLen++] = SLASH;
  146.             Dir[SLen  ] = 0L;
  147.         }
  148.     }
  149.  
  150.     strcat(Dir, File);
  151. }
  152.  
  153.  
  154. /*
  155.  * Quick replace function
  156.  * Replaces every occurrence of a character in a string with another one.
  157.  */
  158.  
  159. void strrep(          STRPTR String,            /* String to replace within.    */
  160.                 const UBYTE From,                /* Character to search for.        */
  161.                 const UBYTE To)                    /* Character to put instead.    */
  162. {
  163.     while(String = strchr(String, From))
  164.         *String++ = To;
  165. }
  166.  
  167.  
  168.  
  169. /*
  170.  * Strips tail and/or front of a string
  171.  * Kills trailing/leading spaces. The macro/function SKIP_STRIP(char c)
  172.  * is used to decide whether a space should be skipped. This function
  173.  * should return TRUE if the character should be skipped, FALSE if not.
  174.  * Returns the string which was passed onto it.
  175.  */
  176.  
  177.  
  178. STRPTR strip(      STRPTR str,        /* String to strip */
  179.             const WORDBITS flags)    /* One of the following:             */
  180.                                     /* STRP_LFT - Strips leading  blanks */
  181.                                     /* STRP_RGT - Strips trailing blanks */
  182.                                     /* STRP_BTH - Strips on both sides     */
  183. {
  184.     STRPTR bufptr = str, nlptr;
  185.     UBYTE c;
  186.  
  187.     if(bufptr && (c = *bufptr))
  188.     {
  189.         if(flags & STRP_LFT)
  190.         {
  191.             if(SKIP_STRIP(c) && c)
  192.             {
  193.                 do
  194.                 {
  195.                     c = *++bufptr;
  196.                 } while(SKIP_STRIP(c) && c);
  197.             }
  198.         }
  199.  
  200.         if(flags & STRP_RGT)
  201.         {
  202.             if(c && *bufptr)
  203.             {
  204.                 nlptr = bufptr;
  205.  
  206.                 while(*++nlptr);
  207.  
  208.                 do
  209.                 {
  210.                     nlptr[0] = 0;
  211.                     c = *--nlptr;
  212.                 } while(SKIP_STRIP(c) && c && (nlptr > bufptr));
  213.  
  214.             }
  215.             else
  216.                 *bufptr = 0;
  217.         }
  218.     }
  219.     return(bufptr);
  220. }
  221.  
  222.  
  223. /*
  224.  * Make a sign of life.
  225.  * Displays a rotating line, displayed using the characters \|/-. Each
  226.  * call will progress the line one position. Useful for notifying the user
  227.  * that something in fact is happening.
  228.  *
  229.  */
  230.  
  231. void tictoc(void)
  232. {
  233. #ifndef    NO_TICTOC
  234. static const
  235.     UBYTE    Frames [] = "\\|/-";
  236.  
  237. static
  238.     UWORD    Offset = 0L;
  239.  
  240.     putc(Frames[Offset++], stderr);
  241.     putc('\r', stderr);
  242.     fflush(stderr);
  243.  
  244.     Offset &= 3;
  245. #else
  246.     return;
  247. #endif
  248. }
  249.  
  250. /*
  251.  * Converts all the chars in the string passed into uppercase.
  252.  */
  253.  
  254. #ifdef STRUPR_NEED
  255. STRPTR strupr(STRPTR String)
  256. {
  257.     STRPTR    Bufptr;
  258.     UBYTE    TmpC;
  259.  
  260.     for(Bufptr = String;
  261.         TmpC = *Bufptr;
  262.         Bufptr++)
  263.         *Bufptr = toupper(TmpC);
  264.  
  265.     return(String);
  266. }
  267. #endif
  268.  
  269. /*
  270.  * Returns a duplicate of the string passed.
  271.  */
  272.  
  273. #ifdef STRDUP_NEED
  274. STRPTR strdup(const STRPTR String)
  275. {
  276.     STRPTR    Retval = NULL;
  277.     size_t    Len;
  278.  
  279.     if(String)
  280.     {
  281.         Len = strlen(String) + 1;
  282.         if(Retval = malloc(strlen(String) + 1))
  283.         {
  284.             memcpy(Retval, String, Len);
  285.         }
  286.     }
  287.  
  288.     return(Retval);
  289. }
  290. #endif
  291.  
  292. /*
  293.  * Allocates a with the length n, and copies the contents of `b' into
  294.  * that one.
  295.  */
  296.  
  297. void *realloc_ (void *b, size_t n)
  298. {
  299.     void    *Retval = NULL;
  300.  
  301.     if(n)
  302.     {
  303.         if((Retval = calloc(n, sizeof(UBYTE))) && b)
  304.         {
  305.             memcpy(Retval, b, n);
  306.             free(b);
  307.         }
  308.     }
  309.     else
  310.         free(b);
  311.  
  312.     return(Retval);
  313. }
  314.  
  315.  
  316. /*************************** WORDLIST HANDLING **************************/
  317.  
  318. /*
  319.  * Inserts a duplicate of `Word' into the `Wordlist' structure. You do thus
  320.  * not need to make a duplicate of `Word' yourself.
  321.  */
  322.  
  323. BOOL InsertWord(const STRPTR Word, struct WordList *WL)
  324. {
  325.     STRPTR    WrdCpy;
  326.  
  327.     if(WrdCpy = strdup(Word))
  328.     {
  329.         if(StkPush(WrdCpy, &WL->Stack))
  330.         {
  331.             WL->Sorted = FALSE;
  332.             return(TRUE);
  333.         }
  334.         free(WrdCpy);
  335.     }
  336.  
  337.     return(FALSE);
  338. }
  339.  
  340. /*
  341.  * Query whether a `Word' is previously InsertWord()'ed into the WL
  342.  * structure. Does case-sensitive comparison.
  343.  */
  344.  
  345.  
  346. BOOL HasWord(const STRPTR Word, struct WordList *WL)
  347. {
  348.     if(WL && WL->Stack.Used && Word)
  349.     {
  350.         ifn(WL->Sorted)
  351.         {
  352.             qsort(&WL->Stack.Data[0], (size_t) WL->Stack.Used, sizeof(APTR), &str_cmp);
  353.             WL->Sorted = TRUE;
  354.         }
  355.  
  356.         if(bsearch(&Word, &WL->Stack.Data[0], (size_t) WL->Stack.Used, sizeof(APTR), &str_cmp))
  357.             return(TRUE);
  358.     }
  359.     return(FALSE);
  360. }
  361.  
  362.  
  363. int str_cmp(const void *a, const void *b)
  364. {
  365.     return(strcmp(*((STRPTR *) a), *((STRPTR *) b)));
  366. }
  367.  
  368. /************************** GENERIC STACK  ******************************/
  369.  
  370. /*
  371.  * Push something onto a stack. Returns TRUE if successful, else FALSE.
  372.  * Note: You can not push a NULL Data element.
  373.  */
  374.  
  375. BOOL StkPush(const APTR Data, struct Stack *Stack)
  376. {
  377.     ULONG    NewSize;
  378.     APTR    *NewBuf;
  379.  
  380.     if(Data && Stack)
  381.     {
  382.         if(Stack->Used >= Stack->Size)
  383.         {
  384.             NewSize =    Stack->Size?
  385.                         (Stack->Size * 3)/2 :
  386.                         MINPUDDLE * sizeof(APTR);
  387.  
  388.             if(NewBuf = realloc(Stack->Data, (size_t) NewSize))
  389.             {
  390.                 Stack->Size = NewSize;
  391.                 Stack->Data = NewBuf;
  392.             }
  393.             else
  394.                 return(FALSE);
  395.         }
  396.  
  397.         Stack->Data[Stack->Used++] = Data;
  398.         return(TRUE);
  399.     }
  400.  
  401.     return(FALSE);
  402. }
  403.  
  404. /*
  405.  * Pops an element from the stack.
  406.  *
  407.  */
  408.  
  409. APTR StkPop(struct Stack *Stack)
  410. {
  411.     APTR    Retval = NULL;
  412.  
  413.     if(Stack && (Stack->Used > 0))
  414.     {
  415.         Retval = Stack->Data[--Stack->Used];
  416.  
  417. #ifdef NO_DIRTY_TRICKS
  418.         {
  419.             APTR    *NewBuf;
  420.  
  421.             if(Stack->Used < (Stack->Size/2))
  422.             {
  423.                 ULONG    NewSize;
  424.                 NewSize = (Stack->Size * 2)/3;
  425.                 NewSize = max(NewSize, MINPUDDLE * sizeof(APTR));
  426.  
  427.                 if(NewBuf = realloc(Stack->Data, (size_t) NewSize))
  428.                 {
  429.                     Stack->Size    = NewSize;
  430.                     Stack->Data    = NewBuf;
  431.                 }
  432.             }
  433.         }
  434. #endif
  435.     }
  436.     return(Retval);
  437. }
  438.  
  439. /*
  440.  * Returns the topmost element of the stack.
  441.  */
  442.  
  443. APTR StkTop(struct Stack *Stack)
  444. {
  445.     APTR    Retval = NULL;
  446.  
  447.     if(Stack && (Stack->Used > 0))
  448.         Retval = Stack->Data[Stack->Used - 1];
  449.  
  450.     return(Retval);
  451. }
  452.  
  453. /************************** CHARACTER STACK ******************************/
  454.  
  455. /*
  456.  * Pushes the character on the stack.
  457.  */
  458.  
  459. BOOL PushChar(const UBYTE c, const ULONG Line,
  460.               const ULONG Column, struct Stack *Stk,
  461.               const STRPTR LineCpy)
  462. {
  463.     struct CharInfo    *ci;
  464.  
  465.     if(ci = malloc(sizeof(struct CharInfo)))
  466.     {
  467.         ci->Char = c;
  468.         ci->Line = Line;
  469.         ci->Column = Column;
  470.         ci->LineBuf = LineCpy;
  471.         if(StkPush(ci, Stk))
  472.         {
  473.             return(TRUE);
  474.         }
  475.         free(ci);
  476.     }
  477.  
  478.     return(FALSE);
  479. }
  480.  
  481. /*
  482.  * Returns and removes a character from the stack, returns NULL if
  483.  * the stack is empty.
  484.  */
  485.  
  486.  
  487. struct CharInfo *PopChar(struct Stack *Stack)
  488. {
  489.     return((struct CharInfo *) StkPop(Stack));
  490. }
  491.  
  492. /*
  493.  * Same as PopChar(), but lets the character alone on the stack.
  494.  */
  495.  
  496.  
  497. struct CharInfo *TopChar(struct Stack *Stack)
  498. {
  499.     return((struct CharInfo *) StkTop(Stack));
  500. }
  501.  
  502.  
  503. /************************* OPEN/CLOSE COUNTING **************************/
  504.  
  505. /*
  506.  * Returns the index a given bracket (`()[]{}') character has in the
  507.  * BrOrder array. Returns ~0 if the character was not a bracket.
  508.  */
  509.  
  510. ULONG BrackIndex(const UBYTE c)
  511. {
  512.     ptrdiff_t    Retval;
  513.  
  514.     /*
  515.      * We should really use a strchr() into the BrOrder array,
  516.      * but this is hopefully faster...this routine is one of the
  517.      * most called functions in the whole program.
  518.      */
  519.  
  520. #ifndef    NO_DIRTY_TRICKS
  521.     switch(c)
  522.     {
  523.     case '(':    Retval = 0;        break;
  524.     case ')':    Retval = 1;        break;
  525.     case '[':    Retval = 2;        break;
  526.     case ']':    Retval = 3;        break;
  527.     case '{':    Retval = 4;     break;
  528.     case '}':    Retval = 5;     break;
  529.     default:    Retval = ~0UL;    break;
  530.     }
  531. #else
  532.     {
  533.         STRPTR        Ptr;
  534.  
  535.         Retval = ~0UL;
  536.  
  537.         if(c && (Ptr = strchr(BrOrder, c)))
  538.             Retval = Ptr - BrOrder;
  539.     }
  540. #endif
  541.  
  542.     return((ULONG) Retval);
  543. }
  544.  
  545. /*
  546.  * Counts brackets for you. Give it a bracket, and it will update the
  547.  * corresponding counter.
  548.  */
  549.  
  550. void AddBracket(const UBYTE c)
  551. {
  552.     LONG    Index;
  553.  
  554.     if((Index = BrackIndex(c)) != ~0UL)
  555.     {
  556.         Brackets[Index]++;
  557.     }
  558. }
  559.  
  560. /*
  561.  * Returns the character that matches the given bracket, NULL if `c'
  562.  * wasn't a bracket character.
  563.  */
  564.  
  565. UBYTE MatchBracket(const UBYTE c)
  566. {
  567.     ULONG    Index;
  568.     UBYTE    Char = 0;
  569.  
  570.  
  571.     if((Index = BrackIndex(c)) != ~0UL)
  572.         Char = BrOrder[Index ^ 1];
  573.  
  574.     return(Char);
  575. }
  576.  
  577.